#include "GLTextureManager.h"
#include "MWResourceManager.h"
#include "MWImage.h"

namespace Myway {

	GLTextureManager::GLTextureManager()
	{
	}

	GLTextureManager::~GLTextureManager()
	{
		d_assert (mTextures.Size() == 0);
	}

	TexturePtr GLTextureManager::CreateTexture(const TString128 & sName, int iWidth, int iHeight, int iMipLevel, PIXEL_FORMAT Format, USAGE usage)
	{
		d_assert (FindTexture(sName) == NULL);

		d_assert (Format == PF_A8R8G8B8);

		void * data = (void *) new char[4 * iWidth * iHeight];
		memset(data, 0, 4 * iWidth * iHeight);

		GLuint texture;
		glGenTextures(1, &texture);
		glBindTexture(GL_TEXTURE_2D, texture);

		glTexImage2D(GL_TEXTURE_2D, 0, 4, iWidth, iHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);

		delete data;

		GLTexture * p = new GLTexture;

		p->mName = sName;
		p->mSourceName = "";
		p->mWidth = iWidth;
		p->mHeight = iHeight;
		p->mMipLevels = 1;
		p->mUsage = USAGE_STATIC;
		p->mFormat = PF_A8R8G8B8;
		p->mGLTexture = texture;

		mTextures.Insert(p->GetName(), p);

		return p;

		return NULL;
	}

	TexturePtr GLTextureManager::LoadTexture(const TString128 & name, const TString128 & source, bool inFileSystem)
	{
		TexturePtr t = FindTexture(name);

		if (t != NULL)
			return t;

		//
		DataStreamPtr stream = ResourceManager::Instance()->OpenResource(source.c_str(), inFileSystem);

		if (stream == NULL)
		{
			LOG_PRINT_FORMAT ("Error: texture '%s' can't open.\n", source.c_str());
			return NULL;
		}

		MImage img;

		if (!img.LoadFromStream(stream))
		{
			LOG_PRINT_FORMAT ("Error: texture '%s' can't load.\n", source.c_str());
			return NULL;
		}

		GLuint texture;
		glGenTextures(1, &texture);
		glBindTexture(GL_TEXTURE_2D, texture);

		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

		//img.ToPower2();
		//gluBuild2DMipmaps(GL_TEXTURE_2D, 4, img.GetWidth(), img.GetHeight(), GL_RGBA, GL_UNSIGNED_BYTE, img.GetColorData());
		glTexImage2D(GL_TEXTURE_2D, 0, 4, img.GetWidth(), img.GetHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, img.GetColorData());

		GLTexture * p = new GLTexture;

		p->mName = name;
		p->mSourceName = stream->GetName();
		p->mWidth = img.GetWidth();
		p->mHeight = img.GetHeight();
		p->mMipLevels = 1;
		p->mUsage = USAGE_STATIC;
		p->mFormat = PF_A8R8G8B8;
		p->mGLTexture = texture;

		mTextures.Insert(p->GetName(), p);

		return p;
	}

	TexturePtr GLTextureManager::LoadTextureFromStream(const TString128 & name, DataStreamPtr stream)
	{
		TexturePtr t = FindTexture(name);

		if (t != NULL)
			return t;

		//
		d_assert (stream != NULL);

		MImage img;

		if (!img.LoadFromStream(stream))
		{
			LOG_PRINT_FORMAT ("Error: texture '%s' can't load.\n", stream->GetName().c_str());
			return NULL;
		}

		GLuint texture;
		glGenTextures(1, &texture);
		glBindTexture(GL_TEXTURE_2D, texture);

		glTexImage2D(GL_TEXTURE_2D, 0, 4, img.GetWidth(), img.GetHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, img.GetColorData());

		GLTexture * p = new GLTexture;

		p->mName = name;
		p->mSourceName = stream->GetName();
		p->mWidth = img.GetWidth();
		p->mHeight = img.GetHeight();
		p->mMipLevels = 1;
		p->mUsage = USAGE_STATIC;
		p->mFormat = PF_A8R8G8B8;
		p->mGLTexture = texture;

		mTextures.Insert(p->GetName(), p);

		return p;
	}

	TexturePtr GLTextureManager::FindTexture(const TString128 & name)
	{
		Texture2DMap::Iterator iter0 = mTextures.Find(name);
		Texture2DMap::Iterator end0 = mTextures.End();

		if (iter0 != end0)
			return TexturePtr(iter0->second);

		return TexturePtr();
	}

	void GLTextureManager::DestroyTexture(Texture * pTexture)
	{
		Texture2DMap::Iterator iter = mTextures.Find(pTexture->GetName());
		Texture2DMap::Iterator end = mTextures.End();

		assert(iter != end);

		delete iter->second;

		mTextures.Erase(iter);
	}


}